 define(function(require, exports, moudles) {

     var $ = require("$"),
         app = require("dist/application/app"),
         swfobject = require("./swfobject"),
         config = app.config;
     require("./swfupload");
     (function($) {

         // These methods can be called by adding them as the first argument in the uploadify plugin call
         var methods = {

             init: function(options, swfUploadOptions) {

                 return this.each(function() {

                     // Create a reference to the jQuery DOM object
                     var $this = $(this);

                     // Clone the original DOM object
                     var $clone = $this.clone();

                     // Setup the default options
                     var settings = $.extend({
                         // Required Settings
                         id: $this.attr('id'), // The ID of the DOM object
                         swf: 'uploadify.swf', // The path to the uploadify SWF file
                         uploader: 'uploadify.php', // The path to the server-side upload script

                         // Options
                         auto: true, // Automatically upload files when added to the queue
                         buttonClass: '', // A class name to add to the browse button DOM object
                         buttonCursor: 'hand', // The cursor to use with the browse button
                         buttonImage: null, // (String or null) The path to an image to use for the Flash browse button if not using CSS to style the button
                         buttonText: 'SELECT FILES', // The text to use for the browse button
                         checkExisting: false, // The path to a server-side script that checks for existing files on the server
                         debug: false, // Turn on swfUpload debugging mode
                         fileObjName: 'Filedata', // The name of the file object to use in your server-side script
                         fileSizeLimit: 0, // The maximum size of an uploadable file in KB (Accepts units B KB MB GB if string, 0 for no limit)
                         fileTypeDesc: 'All Files', // The description for file types in the browse dialog
                         fileTypeExts: '*.*', // Allowed extensions in the browse dialog (server-side validation should also be used)
                         height: 30, // The height of the browse button
                         method: 'post', // The method to use when sending files to the server-side upload script
                         multi: true, // Allow multiple file selection in the browse dialog
                         formData: {}, // An object with additional data to send to the server-side upload script with every file upload
                         preventCaching: true, // Adds a random value to the Flash URL to prevent caching of it (conflicts with existing parameters)
                         progressData: 'percentage', // ('percentage' or 'speed') Data to show in the queue item during a file upload
                         queueID: false, // The ID of the DOM object to use as a file queue (without the #)
                         queueSizeLimit: 999, // The maximum number of files that can be in the queue at one time
                         removeCompleted: true, // Remove queue items from the queue when they are done uploading
                         removeTimeout: 3, // The delay in seconds before removing a queue item if removeCompleted is set to true
                         requeueErrors: false, // Keep errored files in the queue and keep trying to upload them
                         successTimeout: 30, // The number of seconds to wait for Flash to detect the server's response after the file has finished uploading
                         uploadLimit: 0, // The maximum number of files you can upload
                         width: 100, // The width of the browse button

                         // Events
                         overrideEvents: [] // (Array) A list of default event handlers to skip
                         /*
                    onCancel         // Triggered when a file is cancelled from the queue
                    onClearQueue     // Triggered during the 'clear queue' method
                    onDestroy        // Triggered when the uploadify object is destroyed
                    onDialogClose    // Triggered when the browse dialog is closed
                    onDialogOpen     // Triggered when the browse dialog is opened
                    onDisable        // Triggered when the browse button gets disabled
                    onEnable         // Triggered when the browse button gets enabled
                    onFallback       // Triggered is Flash is not detected    
                    onInit           // Triggered when Uploadify is initialized
                    onQueueComplete  // Triggered when all files in the queue have been uploaded
                    onSelectError    // Triggered when an error occurs while selecting a file (file size, queue size limit, etc.)
                    onSelect         // Triggered for each file that is selected
                    onSWFReady       // Triggered when the SWF button is loaded
                    onUploadComplete // Triggered when a file upload completes (success or error)
                    onUploadError    // Triggered when a file upload returns an error
                    onUploadSuccess  // Triggered when a file is uploaded successfully
                    onUploadProgress // Triggered every time a file progress is updated
                    onUploadStart    // Triggered immediately before a file upload starts
                    */
                     }, options);

                     // Prepare settings for SWFUpload
                     var swfUploadSettings = {
                         assume_success_timeout: settings.successTimeout,
                         button_placeholder_id: settings.id,
                         button_width: settings.width,
                         button_height: settings.height,
                         button_text: null,
                         button_text_style: null,
                         button_text_top_padding: 0,
                         button_text_left_padding: 0,
                         button_action: (settings.multi ? SWFUpload.BUTTON_ACTION.SELECT_FILES : SWFUpload.BUTTON_ACTION.SELECT_FILE),
                         button_disabled: false,
                         button_cursor: (settings.buttonCursor == 'arrow' ? SWFUpload.CURSOR.ARROW : SWFUpload.CURSOR.HAND),
                         button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
                         debug: settings.debug,
                         requeue_on_error: settings.requeueErrors,
                         file_post_name: settings.fileObjName,
                         file_size_limit: settings.fileSizeLimit,
                         file_types: settings.fileTypeExts,
                         file_types_description: settings.fileTypeDesc,
                         file_queue_limit: settings.queueSizeLimit,
                         file_upload_limit: settings.uploadLimit,
                         flash_url: settings.swf,
                         prevent_swf_caching: settings.preventCaching,
                         post_params: settings.formData,
                         upload_url: settings.uploader,
                         use_query_string: (settings.method == 'get'),

                         // Event Handlers 
                         file_dialog_complete_handler: handlers.onDialogClose,
                         file_dialog_start_handler: handlers.onDialogOpen,
                         file_queued_handler: handlers.onSelect,
                         file_queue_error_handler: handlers.onSelectError,
                         swfupload_loaded_handler: settings.onSWFReady,
                         upload_complete_handler: handlers.onUploadComplete,
                         upload_error_handler: handlers.onUploadError,
                         upload_progress_handler: handlers.onUploadProgress,
                         upload_start_handler: handlers.onUploadStart,
                         upload_success_handler: handlers.onUploadSuccess
                     }

                     // Merge the user-defined options with the defaults
                     if (swfUploadOptions) {
                         swfUploadSettings = $.extend(swfUploadSettings, swfUploadOptions);
                     }
                     // Add the user-defined settings to the swfupload object
                     swfUploadSettings = $.extend(swfUploadSettings, settings);

                     // Detect if Flash is available
                     var playerVersion = swfobject.getFlashPlayerVersion();
                     var flashInstalled = (playerVersion.major >= 9);

                     if (flashInstalled) {
                         // Create the swfUpload instance
                         window['uploadify_' + settings.id] = new SWFUpload(swfUploadSettings);
                         var swfuploadify = window['uploadify_' + settings.id];

                         // Add the SWFUpload object to the elements data object
                         $this.data('uploadify', swfuploadify);

                         // Wrap the instance
                         var $wrapper = $('<div />', {
                             'id': settings.id,
                             'class': 'uploadify'
                         });
                         $('#' + swfuploadify.movieName).wrap($wrapper);
                         // Recreate the reference to wrapper
                         $wrapper = $('#' + settings.id);
                         // Add the data object to the wrapper 
                         $wrapper.data('uploadify', swfuploadify);

                         // Create the button
                         var $button = $('<button  />', {
                             'id': settings.id + '-button',
                             'class': '' + settings.buttonClass,
                             'type': 'button'
                         });
                         if (settings.buttonImage) {
                             $button.css({
                                 'background-image': "url('" + settings.buttonImage + "')",
                                 'text-indent': '-9999px'
                             });
                         }
                         $button.html('<span class="uploadify-button-text">' + settings.buttonText + '</span>')
                         //.css({
                         //  'height'      : settings.height + 'px',
                         //  'line-height' : settings.height + 'px',
                         //  'width'       : settings.width + 'px'
                         //});
                         // Append the button to the wrapper
                         $wrapper.append($button);

                         // Adjust the styles of the movie
                         $('#' + swfuploadify.movieName).css({
                             'position': 'absolute',
                             'z-index': 1
                         });

                         // Create the file queue
                         if (!settings.queueID) {
                             var $queue = $('<div />', {
                                 'id': settings.id + '-queue',
                                 'class': 'uploadify-queue'
                             });
                             $wrapper.after($queue);
                             swfuploadify.settings.queueID = settings.id + '-queue';
                             swfuploadify.settings.defaultQueue = true;
                         }

                         // Create some queue related objects and variables
                         swfuploadify.queueData = {
                             files: {}, // The files in the queue
                             filesSelected: 0, // The number of files selected in the last select operation
                             filesQueued: 0, // The number of files added to the queue in the last select operation
                             filesReplaced: 0, // The number of files replaced in the last select operation
                             filesCancelled: 0, // The number of files that were cancelled instead of replaced
                             filesErrored: 0, // The number of files that caused error in the last select operation
                             uploadsSuccessful: 0, // The number of files that were successfully uploaded
                             uploadsErrored: 0, // The number of files that returned errors during upload
                             averageSpeed: 0, // The average speed of the uploads in KB
                             queueLength: 0, // The number of files in the queue
                             queueSize: 0, // The size in bytes of the entire queue
                             uploadSize: 0, // The size in bytes of the upload queue
                             queueBytesUploaded: 0, // The size in bytes that have been uploaded for the current upload queue
                             uploadQueue: [], // The files currently to be uploaded
                             errorMsg: '其中有些文件无法上传:'
                         };

                         // Save references to all the objects
                         swfuploadify.original = $clone;
                         swfuploadify.wrapper = $wrapper;
                         swfuploadify.button = $button;
                         swfuploadify.queue = $queue;

                         // Call the user-defined init event handler
                         if (settings.onInit) settings.onInit.call($this, swfuploadify);

                     } else {

                         // Call the fallback function
                         if (settings.onFallback) settings.onFallback.call($this);

                     }
                 });

             },

             // Stop a file upload and remove it from the queue 
             cancel: function(fileID, supressEvent) {

                 var args = arguments;

                 this.each(function() {
                     // Create a reference to the jQuery DOM object
                     var $this = $(this),
                         swfuploadify = $this.data('uploadify'),
                         settings = swfuploadify.settings,
                         delay = -1;

                     if (args[0]) {
                         // Clear the queue
                         if (args[0] == '*') {
                             var queueItemCount = swfuploadify.queueData.queueLength;
                             $('#' + settings.queueID).find('.uploadify-queue-item').each(function() {
                                 delay++;
                                 if (args[1] === true) {
                                     swfuploadify.cancelUpload($(this).attr('id'), false);
                                 } else {
                                     swfuploadify.cancelUpload($(this).attr('id'));
                                 }
                                 $(this).find('.data').removeClass('data').html(' - Cancelled');
                                 $(this).find('.uploadify-progress-bar').remove();
                                 $(this).delay(1000 + 100 * delay).fadeOut(500, function() {
                                     $(this).remove();
                                 });
                             });
                             swfuploadify.queueData.queueSize = 0;
                             // Trigger the onClearQueue event
                             if (settings.onClearQueue) settings.onClearQueue.call($this, queueItemCount);
                         } else {
                             for (var n = 0; n < args.length; n++) {
                                 swfuploadify.cancelUpload(args[n]);
                                 $('#' + args[n]).find('.data').removeClass('data').html(' - Cancelled');
                                 $('#' + args[n]).find('.uploadify-progress-bar').remove();
                                 $('#' + args[n]).delay(1000 + 100 * n).fadeOut(500, function() {
                                     $(this).remove();
                                 });
                             }
                         }
                     } else {
                         var item = $('#' + settings.queueID).find('.uploadify-queue-item').get(0);
                         $item = $(item);
                         swfuploadify.cancelUpload($item.attr('id'));
                         $item.find('.data').removeClass('data').html(' - Cancelled');
                         $item.find('.uploadify-progress-bar').remove();
                         $item.delay(1000).fadeOut(500, function() {
                             $(this).remove();
                         });
                     }
                 });

             },

             // Revert the DOM object back to its original state
             destroy: function() {

                 this.each(function() {
                     // Create a reference to the jQuery DOM object
                     var $this = $(this),
                         swfuploadify = $this.data('uploadify'),
                         settings = swfuploadify.settings;

                     // Destroy the SWF object and 
                     swfuploadify.destroy();

                     // Destroy the queue
                     if (settings.defaultQueue) {
                         $('#' + settings.queueID).remove();
                     }

                     // Reload the original DOM element
                     $('#' + settings.id).replaceWith(swfuploadify.original);

                     // Call the user-defined event handler
                     if (settings.onDestroy) settings.onDestroy.call(this);

                     delete swfuploadify;
                 });

             },

             // Disable the select button
             disable: function(isDisabled) {

                 this.each(function() {
                     // Create a reference to the jQuery DOM object
                     var $this = $(this),
                         swfuploadify = $this.data('uploadify'),
                         settings = swfuploadify.settings;

                     // Call the user-defined event handlers
                     if (isDisabled) {
                         swfuploadify.button.addClass('disabled');
                         if (settings.onDisable) settings.onDisable.call(this);
                     } else {
                         swfuploadify.button.removeClass('disabled');
                         if (settings.onEnable) settings.onEnable.call(this);
                     }

                     // Enable/disable the browse button
                     swfuploadify.setButtonDisabled(isDisabled);
                 });

             },

             // Get or set the settings data
             settings: function(name, value, resetObjects) {

                 var args = arguments;
                 var returnValue = value;

                 this.each(function() {
                     // Create a reference to the jQuery DOM object
                     var $this = $(this),
                         swfuploadify = $this.data('uploadify'),
                         settings = swfuploadify.settings;

                     if (typeof(args[0]) == 'object') {
                         for (var n in value) {
                             setData(n, value[n]);
                         }
                     }
                     if (args.length === 1) {
                         returnValue = settings[name];
                     } else {
                         switch (name) {
                             case 'uploader':
                                 swfuploadify.setUploadURL(value);
                                 break;
                             case 'formData':
                                 if (!resetObjects) {
                                     value = $.extend(settings.formData, value);
                                 }
                                 swfuploadify.setPostParams(settings.formData);
                                 break;
                             case 'method':
                                 if (value == 'get') {
                                     swfuploadify.setUseQueryString(true);
                                 } else {
                                     swfuploadify.setUseQueryString(false);
                                 }
                                 break;
                             case 'fileObjName':
                                 swfuploadify.setFilePostName(value);
                                 break;
                             case 'fileTypeExts':
                                 swfuploadify.setFileTypes(value, settings.fileTypeDesc);
                                 break;
                             case 'fileTypeDesc':
                                 swfuploadify.setFileTypes(settings.fileTypeExts, value);
                                 break;
                             case 'fileSizeLimit':
                                 swfuploadify.setFileSizeLimit(value);
                                 break;
                             case 'uploadLimit':
                                 swfuploadify.setFileUploadLimit(value);

                                 break;
                             case 'queueSizeLimit':
                                 swfuploadify.setFileQueueLimit(value);
                                 break;
                             case 'buttonImage':
                                 swfuploadify.button.css('background-image', settingValue);
                                 break;
                             case 'buttonCursor':
                                 if (value == 'arrow') {
                                     swfuploadify.setButtonCursor(SWFUpload.CURSOR.ARROW);
                                 } else {
                                     swfuploadify.setButtonCursor(SWFUpload.CURSOR.HAND);
                                 }
                                 break;
                             case 'buttonText':
                                 $('#' + settings.id + '-button').find('.uploadify-button-text').html(value);
                                 break;
                             case 'width':
                                 swfuploadify.setButtonDimensions(value, settings.height);
                                 break;
                             case 'height':
                                 swfuploadify.setButtonDimensions(settings.width, value);
                                 break;
                             case 'multi':
                                 if (value) {
                                     swfuploadify.setButtonAction(SWFUpload.BUTTON_ACTION.SELECT_FILES);
                                 } else {
                                     swfuploadify.setButtonAction(SWFUpload.BUTTON_ACTION.SELECT_FILE);
                                 }
                                 break;
                         }
                         settings[name] = value;
                     }
                 });

                 if (args.length === 1) {
                     return returnValue;
                 }

             },

             // Stop the current uploads and requeue what is in progress
             stop: function() {

                 this.each(function() {
                     // Create a reference to the jQuery DOM object
                     var $this = $(this),
                         swfuploadify = $this.data('uploadify');

                     // Reset the queue information
                     swfuploadify.queueData.averageSpeed = 0;
                     swfuploadify.queueData.uploadSize = 0;
                     swfuploadify.queueData.bytesUploaded = 0;
                     swfuploadify.queueData.uploadQueue = [];

                     swfuploadify.stopUpload();
                 });

             },

             // Start uploading files in the queue
             upload: function() {

                 var args = arguments;

                 this.each(function() {
                     // Create a reference to the jQuery DOM object
                     var $this = $(this),
                         swfuploadify = $this.data('uploadify');

                     // Reset the queue information
                     swfuploadify.queueData.averageSpeed = 0;
                     swfuploadify.queueData.uploadSize = 0;
                     swfuploadify.queueData.bytesUploaded = 0;
                     swfuploadify.queueData.uploadQueue = [];

                     // Upload the files
                     if (args[0]) {
                         if (args[0] == '*') {
                             swfuploadify.queueData.uploadSize = swfuploadify.queueData.queueSize;
                             swfuploadify.queueData.uploadQueue.push('*');
                             swfuploadify.startUpload();
                         } else {
                             for (var n = 0; n < args.length; n++) {
                                 swfuploadify.queueData.uploadSize += swfuploadify.queueData.files[args[n]].size;
                                 swfuploadify.queueData.uploadQueue.push(args[n]);
                             }
                             swfuploadify.startUpload(swfuploadify.queueData.uploadQueue.shift());
                         }
                     } else {
                         swfuploadify.startUpload();
                     }

                 });

             }

         }

         // These functions handle all the events that occur with the file uploader
         var handlers = {

             // Triggered when the file dialog is opened
             onDialogOpen: function() {
                 // Load the swfupload settings
                 var settings = this.settings;

                 // Reset some queue info
                 this.queueData.errorMsg = '其中有些文件无法上传:';
                 this.queueData.filesReplaced = 0;
                 this.queueData.filesCancelled = 0;

                 // Call the user-defined event handler
                 if (settings.onDialogOpen) settings.onDialogOpen.call(this);
             },

             // Triggered when the browse dialog is closed
             onDialogClose: function(filesSelected, filesQueued, queueLength) {
                 // Load the swfupload settings
                 var settings = this.settings;

                 // Update the queue information
                 this.queueData.filesErrored = filesSelected - filesQueued;
                 this.queueData.filesSelected = filesSelected;
                 this.queueData.filesQueued = filesQueued - this.queueData.filesCancelled;
                 this.queueData.queueLength = queueLength;

                 // Run the default event handler
                 if ($.inArray('onDialogClose', settings.overrideEvents) < 0) {
                     if (this.queueData.filesErrored > 0) {
                         config.msg.info(this.queueData.errorMsg);
                     }
                 }

                 // Call the user-defined event handler
                 if (settings.onDialogClose) settings.onDialogClose.call(this, this.queueData);

                 // Upload the files if auto is true
                 if (settings.auto) $('#' + settings.id).uploadify('upload', '*');
             },

             // Triggered once for each file added to the queue
             onSelect: function(file) {
                 // Load the swfupload settings
                 var settings = this.settings;

                 // Check if a file with the same name exists in the queue
                 var queuedFile = {};
                 for (var n in this.queueData.files) {
                     queuedFile = this.queueData.files[n];
                     if (queuedFile.uploaded != true && queuedFile.name == file.name) {
                         var replaceQueueItem = confirm('The file named "' + file.name + '" is already in the queue.\nDo you want to replace the existing item in the queue?');
                         if (!replaceQueueItem) {
                             this.cancelUpload(file.id);
                             this.queueData.filesCancelled++;
                             return false;
                         } else {
                             $('#' + queuedFile.id).remove();
                             this.cancelUpload(queuedFile.id);
                             this.queueData.filesReplaced++;
                         }
                     }
                 }

                 // Get the size of the file
                 var fileSize = Math.round(file.size / 1024);
                 var suffix = 'KB';
                 if (fileSize > 1000) {
                     fileSize = Math.round(fileSize / 1000);
                     suffix = 'MB';
                 }
                 var fileSizeParts = fileSize.toString().split('.');
                 fileSize = fileSizeParts[0];
                 if (fileSizeParts.length > 1) {
                     fileSize += '.' + fileSizeParts[1].substr(0, 2);
                 }
                 fileSize += suffix;

                 // Truncate the filename if it's too long
                 var fileName = file.name;
                 if (fileName.length > 25) {
                     fileName = fileName.substr(0, 25) + '...';
                 }

                 // Run the default event handler
                 if ($.inArray('onSelect', settings.overrideEvents) < 0) {

                     // Add the file item to the queue
                     $('#' + settings.queueID).append('<div id="' + file.id + '" class="uploadify-queue-item">\
                    <div class="cancel">\
                        <a href="javascript:$(\'#' + settings.id + '\').uploadify(\'cancel\', \'' + file.id + '\')">X</a>\
                    </div>\
                    <span class="fileName">' + fileName + ' (' + fileSize + ')</span><span class="data"></span>\
                    <div class="uploadify-progress">\
                        <div class="uploadify-progress-bar"><!--Progress Bar--></div>\
                    </div>\
                </div>');

                 }

                 this.queueData.queueSize += file.size;
                 this.queueData.files[file.id] = file;

                 // Call the user-defined event handler
                 if (settings.onSelect) settings.onSelect.apply(this, arguments);
             },

             // Triggered when a file is not added to the queue
             onSelectError: function(file, errorCode, errorMsg) {
                 // Load the swfupload settings
                 var settings = this.settings;

                 // Run the default event handler
                 if ($.inArray('onSelectError', settings.overrideEvents) < 0) {
                     switch (errorCode) {
                         case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:
                             if (settings.queueSizeLimit > errorMsg) {
                                 this.queueData.errorMsg += '\n选中的文件数量超过了文件数量上限 (' + errorMsg + ').';
                             } else {
                                 this.queueData.errorMsg += '\n选中的文件数量超过了文件数量上限  (' + settings.queueSizeLimit + ').';
                             }
                             break;
                         case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
                             this.queueData.errorMsg += '\n文件 "' + file.name + '" 超过了尺寸上限 (' + settings.fileSizeLimit + ').';
                             break;
                         case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
                             this.queueData.errorMsg += '\n文件 "' + file.name + '" 是空的.';
                             break;
                         case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
                             this.queueData.errorMsg += '\n文件 "' + file.name + '" 不是允许的文件格式 (' + settings.fileTypeDesc + ').';
                             break;
                     }
                 }
                 if (errorCode != SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED) {
                     delete this.queueData.files[file.id];
                 }

                 // Call the user-defined event handler
                 if (settings.onSelectError) settings.onSelectError.apply(this, arguments);
             },

             // Triggered when all the files in the queue have been processed
             onQueueComplete: function() {
                 if (this.settings.onQueueComplete) this.settings.onQueueComplete.call(this, this.settings.queueData);
             },

             // Triggered when a file upload successfully completes
             onUploadComplete: function(file) {
                 // Load the swfupload settings
                 var settings = this.settings,
                     swfuploadify = this;

                 // Check if all the files have completed uploading
                 var stats = this.getStats();
                 this.queueData.queueLength = stats.files_queued;
                 if (this.queueData.uploadQueue[0] == '*') {
                     if (this.queueData.queueLength > 0) {
                         this.startUpload();
                     } else {
                         this.queueData.uploadQueue = [];

                         // Call the user-defined event handler for queue complete
                         if (settings.onQueueComplete) settings.onQueueComplete.call(this, this.queueData);
                     }
                 } else {
                     if (this.queueData.uploadQueue.length > 0) {
                         this.startUpload(this.queueData.uploadQueue.shift());
                     } else {
                         this.queueData.uploadQueue = [];

                         // Call the user-defined event handler for queue complete
                         if (settings.onQueueComplete) settings.onQueueComplete.call(this, this.queueData);
                     }
                 }

                 // Call the default event handler
                 if ($.inArray('onUploadComplete', settings.overrideEvents) < 0) {
                     if (settings.removeCompleted) {
                         switch (file.filestatus) {
                             case SWFUpload.FILE_STATUS.COMPLETE:
                                 setTimeout(function() {
                                     if ($('#' + file.id)) {
                                         swfuploadify.queueData.queueSize -= file.size;
                                         delete swfuploadify.queueData.files[file.id]
                                         $('#' + file.id).fadeOut(500, function() {
                                             $(this).remove();
                                         });
                                     }
                                 }, settings.removeTimeout * 1000);
                                 break;
                             case SWFUpload.FILE_STATUS.ERROR:
                                 if (!settings.requeueErrors) {
                                     setTimeout(function() {
                                         if ($('#' + file.id)) {
                                             swfuploadify.queueData.queueSize -= file.size;
                                             delete swfuploadify.queueData.files[file.id];
                                             $('#' + file.id).fadeOut(500, function() {
                                                 $(this).remove();
                                             });
                                         }
                                     }, settings.removeTimeout * 1000);
                                 }
                                 break;
                         }
                     } else {
                         file.uploaded = true;
                     }
                 }

                 // Call the user-defined event handler
                 if (settings.onUploadComplete) settings.onUploadComplete.call(this, file);
             },

             // Triggered when a file upload returns an error
             onUploadError: function(file, errorCode, errorMsg) {
                 // Load the swfupload settings
                 var settings = this.settings;

                 // Set the error string
                 var errorString = 'Error';
                 switch (errorCode) {
                     case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
                         errorString = 'HTTP Error (' + errorMsg + ')';
                         break;
                     case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
                         errorString = 'Missing Upload URL';
                         break;
                     case SWFUpload.UPLOAD_ERROR.IO_ERROR:
                         errorString = 'IO Error';
                         break;
                     case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
                         errorString = 'Security Error';
                         break;
                     case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
                         config.msg.info('上传已达到极限 (' + errorMsg + ').');
                         errorString = 'Exceeds Upload Limit';
                         break;
                     case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
                         errorString = 'Failed';
                         break;
                     case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:
                         break;
                     case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
                         errorString = 'Validation Error';
                         break;
                     case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
                         errorString = 'Cancelled';
                         this.queueData.queueSize -= file.size;
                         if (file.status == SWFUpload.FILE_STATUS.IN_PROGRESS || $.inArray(file.id, this.queueData.uploadQueue) >= 0) {
                             this.queueData.uploadSize -= file.size;
                         }
                         // Trigger the onCancel event
                         if (settings.onCancel) settings.onCancel.call(this, file);
                         delete this.queueData.files[file.id];
                         break;
                     case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
                         errorString = 'Stopped';
                         break;
                 }

                 // Call the default event handler
                 if ($.inArray('onUploadError', settings.overrideEvents) < 0) {

                     if (errorCode != SWFUpload.UPLOAD_ERROR.FILE_CANCELLED && errorCode != SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED) {
                         $('#' + file.id).addClass('uploadify-error');
                     }

                     // Reset the progress bar
                     $('#' + file.id).find('.uploadify-progress-bar').css('width', '1px');

                     // Add the error message to the queue item
                     if (errorCode != SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND && file.status != SWFUpload.FILE_STATUS.COMPLETE) {
                         $('#' + file.id).find('.data').html(' - ' + errorString);
                     }
                 }

                 var stats = this.getStats();
                 this.queueData.uploadsErrored = stats.upload_errors;

                 // Call the user-defined event handler
                 if (settings.onUploadError) settings.onUploadError.call(this, file, errorCode, errorMsg, errorString);
             },

             // Triggered periodically during a file upload
             onUploadProgress: function(file, fileBytesLoaded, fileTotalBytes) {
                 // Load the swfupload settings
                 var settings = this.settings;

                 // Setup all the variables
                 var timer = new Date();
                 var newTime = timer.getTime();
                 var lapsedTime = newTime - this.timer;
                 if (lapsedTime > 500) {
                     this.timer = newTime;
                 }
                 var lapsedBytes = fileBytesLoaded - this.bytesLoaded;
                 this.bytesLoaded = fileBytesLoaded;
                 var queueBytesLoaded = this.queueData.queueBytesUploaded + fileBytesLoaded;
                 var percentage = Math.round(fileBytesLoaded / fileTotalBytes * 100);

                 // Calculate the average speed
                 var suffix = 'KB/s';
                 var mbs = 0;
                 var kbs = (lapsedBytes / 1024) / (lapsedTime / 1000);
                 kbs = Math.floor(kbs * 10) / 10;
                 if (this.queueData.averageSpeed > 0) {
                     this.queueData.averageSpeed = Math.floor((this.queueData.averageSpeed + kbs) / 2);
                 } else {
                     this.queueData.averageSpeed = Math.floor(kbs);
                 }
                 if (kbs > 1000) {
                     mbs = (kbs * .001);
                     this.queueData.averageSpeed = Math.floor(mbs);
                     suffix = 'MB/s';
                 }

                 // Call the default event handler
                 if ($.inArray('onUploadProgress', settings.overrideEvents) < 0) {
                     if (settings.progressData == 'percentage') {
                         $('#' + file.id).find('.data').html(' - ' + percentage + '%');
                     } else if (settings.progressData == 'speed' && lapsedTime > 500) {
                         $('#' + file.id).find('.data').html(' - ' + this.queueData.averageSpeed + suffix);
                     }
                     $('#' + file.id).find('.uploadify-progress-bar').css('width', percentage + '%');
                 }

                 // Call the user-defined event handler
                 if (settings.onUploadProgress) settings.onUploadProgress.call(this, file, fileBytesLoaded, fileTotalBytes, queueBytesLoaded, this.queueData.uploadSize);
             },

             // Triggered right before a file is uploaded
             onUploadStart: function(file) {
                 // Load the swfupload settings
                 var settings = this.settings;

                 var timer = new Date();
                 this.timer = timer.getTime();
                 this.bytesLoaded = 0;
                 if (this.queueData.uploadQueue.length == 0) {
                     this.queueData.uploadSize = file.size;
                 }
                 if (settings.checkExisting) {
                     $.ajax({
                         type: 'POST',
                         async: false,
                         url: settings.checkExisting,
                         data: {
                             filename: file.name
                         },
                         success: function(data) {
                             if (data == 1) {
                                 var overwrite = confirm('A file with the name "' + file.name + '" already exists on the server.\nWould you like to replace the existing file?');
                                 if (!overwrite) {
                                     this.cancelUpload(file.id);
                                     $('#' + file.id).remove();
                                     if (this.queueData.uploadQueue.length > 0 && this.queueData.queueLength > 0) {
                                         if (this.queueData.uploadQueue[0] == '*') {
                                             this.startUpload();
                                         } else {
                                             this.startUpload(this.queueData.uploadQueue.shift());
                                         }
                                     }
                                 }
                             }
                         }
                     });
                 }

                 // Call the user-defined event handler
                 if (settings.onUploadStart) settings.onUploadStart.call(this, file);
             },

             // Triggered when a file upload returns a successful code
             onUploadSuccess: function(file, data, response) {
                 // Load the swfupload settings
                 var settings = this.settings;
                 var stats = this.getStats();
                 this.queueData.uploadsSuccessful = stats.successful_uploads;
                 this.queueData.queueBytesUploaded += file.size;

                 // Call the default event handler
                 if ($.inArray('onUploadSuccess', settings.overrideEvents) < 0) {
                     $('#' + file.id).find('.data').html(' -上传完成 正在加载.....');
                 }

                 // Call the user-defined event handler
                 if (settings.onUploadSuccess) settings.onUploadSuccess.call(this, file, data, response);
             }

         }

         $.fn.uploadify = function(method) {

             if (methods[method]) {
                 return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
             } else if (typeof method === 'object' || !method) {
                 return methods.init.apply(this, arguments);
             } else {
                 $.error('The method ' + method + ' does not exist in $.uploadify');
             }

         }

     })($);
 });
